// ------------------------------------------------------------------------
// 版权信息
// 版权归重庆虫儿飞科技有限公司所有。
// 所有权利保留。
// 官方网站：https://netokit.com
// 许可证信息
// Neto.Kit 项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
// 
// 使用条款
// 使用本代码应遵守相关法律法规和许可证的要求。
// 
// 免责声明
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害，我们不承担任何责任。
// 
// 其他重要信息
// Neto.Kit 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
// 有关 Neto.Kit 项目的其他详细信息，请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
// 
// 更多信息
// 请访问 https://netokit.com 获取更多关于 Neto.Kit 项目的许可证和版权信息。
// ------------------------------------------------------------------------

namespace Neto.Extensions;

/// <summary>
///     Byte 扩展
/// </summary>
public static class ByteExtensions
{
    // Base32 字符集
    private const string Base32Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

    /// <summary>
    ///     将字节数组转换为 Base32 编码字符串
    /// </summary>
    /// <param name="bytes">要转换的字节数组</param>
    /// <returns>Base32 编码字符串</returns>
    public static string ToBase32String(this byte[] bytes)
    {
        // 如果输入为空，返回空字符串
        if (bytes == null || bytes.Length == 0) return string.Empty;

        // 计算输出字符串的长度
        var outputLength = (int)Math.Ceiling(bytes.Length * 8 / 5.0);
        var base32 = new StringBuilder(outputLength);

        // 处理每个字节
        var buffer = 0; // 存储当前的 5 位缓冲区
        var bitsInBuffer = 0; // 当前缓冲区中的位数

        foreach (var b in bytes)
        {
            // 将当前字节添加到缓冲区
            buffer = (buffer << 8) | b;
            bitsInBuffer += 8;

            // 每当缓冲区中的位数达到 5 位的倍数时，进行编码
            while (bitsInBuffer >= 5)
            {
                // 从缓冲区中提取前 5 位
                var index = (buffer >> (bitsInBuffer - 5)) & 0x1F;
                base32.Append(Base32Alphabet[index]);
                bitsInBuffer -= 5;
            }
        }

        // 处理剩余的位
        if (bitsInBuffer > 0)
        {
            // 将剩余的位填充到缓冲区
            var index = (buffer << (5 - bitsInBuffer)) & 0x1F;
            base32.Append(Base32Alphabet[index]);
        }

        // 计算需要的填充字符数量
        var paddingCount = (8 - (base32.Length % 8)) % 8;
        base32.Append(new string('=', paddingCount));

        // 返回编码后的字符串
        return base32.ToString();
    }


    /// <summary>
    ///     将字节数组转换为十六进制字符串。
    /// </summary>
    /// <param name="bytes">要转换的字节数组。</param>
    /// <returns>表示字节数组的十六进制字符串。</returns>
    public static string ToHexString(this byte[] bytes)
    {
        // 使用 StringBuilder 来高效地构建字符串
        var hexString = new StringBuilder(bytes.Length * 2);

        // 遍历每个字节
        foreach (var b in bytes)
            // 将每个字节转换为两位十六进制字符，并添加到 StringBuilder 中
            hexString.AppendFormat("{0:x2}", b);

        // 返回构建好的十六进制字符串
        return hexString.ToString();
    }
}